package com.sky.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.constant.MessageConstant;
import com.sky.context.BaseContext;
import com.sky.dto.*;
import com.sky.entity.AddressBook;
import com.sky.entity.OrderDetail;
import com.sky.entity.Orders;
import com.sky.entity.ShoppingCart;
import com.sky.exception.AddressBookBusinessException;
import com.sky.exception.OrderBusinessException;
import com.sky.mapper.AddressBookMapper;
import com.sky.mapper.OrderDetailMapper;
import com.sky.mapper.OrderMapper;
import com.sky.mapper.ShoppingCartMapper;
import com.sky.result.PageResult;
import com.sky.result.Result;
import com.sky.service.OrderService;
import com.sky.utils.MapUtil;
import com.sky.vo.Nothing;
import com.sky.vo.OrderStatisticsVO;
import com.sky.vo.OrderSubmitVO;
import com.sky.vo.OrderVO;
import com.sky.websocket.WebSocketServer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
@Transactional
public class OrderServiceImpl implements OrderService {

    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private ShoppingCartMapper shoppingCartMapper;
    @Autowired
    private AddressBookMapper addressBookMapper;
    @Autowired
    private OrderDetailMapper orderDetailMapper;
    @Autowired
    private WebSocketServer webSocketServer;


    @Override
    public OrderSubmitVO submitOrder(OrdersSubmitDTO ordersSubmitDTO) {
        //判断地址是否有效
        Long addressBookId = ordersSubmitDTO.getAddressBookId();

        Long currentId = BaseContext.getCurrentId();
        if (addressBookId == null) {
            throw new AddressBookBusinessException(MessageConstant.ADDRESS_BOOK_IS_NULL);
        }
        List<AddressBook> addressBooks = addressBookMapper.seleteAddress(AddressBook.builder().id(addressBookId).build());
        if (addressBooks.size() == 0 || addressBooks == null || addressBooks.get(0) == null) {
            throw new AddressBookBusinessException(MessageConstant.ADDRESS_BOOK_IS_NULL);
        }
        AddressBook addressB = addressBooks.get(0);
        //获取具体地址
        String provinceName = addressB.getProvinceName();
        String cityName = addressB.getCityName();
        String districtName = addressB.getDistrictName();
        String detail = addressB.getDetail();
        String address = provinceName + cityName + districtName + detail;
        String coordinate = MapUtil.getCoordinate(address);
        String origin = MapUtil.getCoordinate(MapUtil.addressOrigin);
        Double distance = MapUtil.getDistance(origin, coordinate);
        if (distance > Double.parseDouble("5000")) {
            throw new AddressBookBusinessException(MessageConstant.ADDRESS_BOOK_IS_FAR);
        }
        //判断购物车是否为空
        List<ShoppingCart> shoppingCartList = shoppingCartMapper.getShoppingCartList(currentId);
        if (shoppingCartList.size() == 0 || shoppingCartList == null) {
            throw new AddressBookBusinessException(MessageConstant.ADDRESS_BOOK_IS_NULL);
        }

        //封装数据
        Orders orders = new Orders();
        BeanUtils.copyProperties(ordersSubmitDTO, orders);
        orders.setPayStatus(Orders.UN_PAID);
        orders.setNumber(String.valueOf(System.currentTimeMillis()));
        orders.setUserId(currentId);
        //orders.setPayStatus(Orders.UN_PAID);
        orders.setStatus(Orders.PENDING_PAYMENT);
        AddressBook addressBook = addressBooks.get(0);
        orders.setPhone(addressBook.getPhone());
        orders.setAddress(addressBook.getDetail());
        orders.setConsignee(addressBook.getConsignee());
        orders.setOrderTime(LocalDateTime.now());
        orders.setUserName(addressB.getConsignee());
        // 将订单数据存储到数据库中
        orderMapper.submitOrder(orders);
        Long id = orders.getId();
        List<OrderDetail> orderDetailList = shoppingCartList.stream()
                .map(shoppingCart -> {
                    OrderDetail orderDetail = new OrderDetail();
                    BeanUtils.copyProperties(shoppingCart, orderDetail);
                    orderDetail.setOrderId(id);
                    return orderDetail;
                }).collect(Collectors.toList());
        orderDetailMapper.addOrderDetail(orderDetailList);
        shoppingCartMapper.deleteShoppingCart(currentId);

        log.info("支付成功的订单{} 下单消息推送", orders.getId());
        JSONObject jsonData = new JSONObject();
        jsonData.put("type", 1);
        jsonData.put("orderId", orders.getId());
        jsonData.put("content", orders.getNumber());
        String s = JSON.toJSONString(jsonData);
        webSocketServer.sendToAllClient(s);
        log.info("支付成功的订单{} 下单消息成功", orders.getId());


       /* OrderSubmitVO orderSubmitVO = new OrderSubmitVO();
        BeanUtils.copyProperties(orders, orderSubmitVO);
        return orderSubmitVO;*/
        return OrderSubmitVO.builder()
                .id(orders.getId())
                .orderNumber(orders.getNumber())
                .orderTime(orders.getOrderTime())
                .orderAmount(orders.getAmount())
                .build();

    }

    @Override
    public PageResult historyOrders(OrdersPageQueryDTO ordersPageQueryDTO) {
        ordersPageQueryDTO.setUserId(BaseContext.getCurrentId());

        PageHelper.startPage(ordersPageQueryDTO.getPage(), ordersPageQueryDTO.getPageSize());

        Page<OrderVO> order = orderMapper.historyOrders(ordersPageQueryDTO);//后面 limit 0,10
//        order.forEach(ord->{
//            List<OrderDetail> byOrderId = orderDetailMapper.findByOrderId(ord.getId());
//            ord.setOrderDetailList(byOrderId);
//        });
        Map<Long, List<OrderDetail>> collect = orderDetailMapper.findByOrder().stream().collect(
                Collectors.groupingBy(
                        ord -> ord.getOrderId()
                )
        );
        order.forEach(or ->
                or.setOrderDetailList(collect.get(or.getId()))
        );
        //  long total = order.getTotal();//总记录数
        //int pages = order.getPages();//总页数
        // List result = order.getResult(); //本页数据

        //4.封装PageResultVo
        PageResult pageResultVo = new PageResult();

        pageResultVo.setTotal(order.getTotal());
        pageResultVo.setRecords(order.getResult());

        return pageResultVo;
    }


    @Override
    public OrderVO orderDetail(Long id) {
        OrderVO ov = orderMapper.findOrderById(id);
        return ov;
    }

    @Override
    public Integer cancelOrder(Long id, Integer status) {
        return orderMapper.cancelOrder(id, status);

    }


    @Override
    public PageResult conditionSearch(OrdersPageQueryDTO ordersPageQueryDTO) {
        ordersPageQueryDTO.setUserId(BaseContext.getCurrentId());
        Integer page = ordersPageQueryDTO.getPage();
        Integer pageSize = ordersPageQueryDTO.getPageSize();

        PageHelper.startPage(page, pageSize);

        Page<OrderVO> orderList = orderMapper.findOrders(ordersPageQueryDTO);//后面 limit 0,10
        // 查询所有的订单明细列表(不区分哪个订单的)
        List<OrderDetail> orderDetailList = orderDetailMapper.findByOrder();
        // 今天就见到了!
        Map<Long, List<OrderDetail>> collect = orderDetailList.stream().collect(Collectors.groupingBy(OrderDetail::getOrderId));

//        Map<Long, List<OrderDetail>> collect = orderDetailMapper.findByOrder().stream().collect(
//                Collectors.groupingBy(
//                        ord -> ord.getOrderId()
//                )
//        );

        orderList.forEach(or -> {
            Long orderId = or.getId();
            List<OrderDetail> orderDetails = collect.get(orderId);
            String dishName = orderDetails.stream().map(OrderDetail::getName).collect(Collectors.joining(","));
            or.setOrderDishes(dishName);
        });


      /*  order.forEach(ord -> {
            List<OrderDetail> byOrderId = orderDetailMapper.findByOrderId(ord.getId());
            StringBuilder sb = new StringBuilder();
            byOrderId.forEach(o -> {
                sb.append(o.getName()).append("*").append(o.getNumber()).append(";");
            });
            ord.setOrderDishes(sb.toString());
        });*/


        long total = orderList.getTotal();//总记录数
        //int pages = order.getPages();//总页数
        List result = orderList.getResult(); //本页数据

        //4.封装PageResultVo
        PageResult pageResultVo = new PageResult();

        pageResultVo.setTotal(total);
        pageResultVo.setRecords(result);

        return pageResultVo;
    }

    @Override
    public OrderStatisticsVO statistics() {
        List<Nothing> orderStatisticsVO = orderMapper.statistics();
        OrderStatisticsVO orderStatistics = new OrderStatisticsVO();
        orderStatisticsVO.forEach(item -> {
            if (item.getStatus() == 3) {
                orderStatistics.setConfirmed(item.getCount());
            }
            if (item.getStatus() == 4) {
                orderStatistics.setDeliveryInProgress(item.getCount());
            }
            if (item.getStatus() == 2) {
                orderStatistics.setToBeConfirmed(item.getCount());
            }
        });
        return orderStatistics;
    }

    @Override
    public Integer confirm(OrdersConfirmDTO ordersConfirmDTO) {

        ordersConfirmDTO.setStatus(Orders.CONFIRMED);
        return orderMapper.confirm(ordersConfirmDTO);
    }

    @Override
    public Integer upderOrder(OrdersCancelDTO ordersCancelDTO) {
        ordersCancelDTO.setStatus(Orders.CANCELLED);
        return orderMapper.upderOrder(ordersCancelDTO);
    }

    @Override
    public Integer rejection(OrdersRejectionDTO rdersRejectionDTO) {
        rdersRejectionDTO.setStatus(Orders.CANCELLED);
        return orderMapper.rejection(rdersRejectionDTO);
    }

    @Override
    public Integer cancelOrderDelivery(Long id) {
        OrdersConfirmDTO ordersConfirmDTO = new OrdersConfirmDTO();
        ordersConfirmDTO.setId(id);
        ordersConfirmDTO.setStatus(Orders.DELIVERY_IN_PROGRESS);
        return orderMapper.confirm(ordersConfirmDTO);
    }

    @Override
    public Integer completeOrder(Long id) {
        OrdersConfirmDTO ordersConfirmDTO = new OrdersConfirmDTO();
        ordersConfirmDTO.setId(id);
        ordersConfirmDTO.setStatus(Orders.COMPLETED);
        return orderMapper.confirm(ordersConfirmDTO);

    }


    @Override
    public Integer moreOrder(Long id) {
        List<ShoppingCart> shoppingCartList = orderDetailMapper.findByOrderId(id).stream().map(orderDetail -> {
            ShoppingCart shoppingCart = new ShoppingCart();
            BeanUtils.copyProperties(orderDetail, shoppingCart);
            shoppingCart.setUserId(BaseContext.getCurrentId());
            shoppingCart.setCreateTime(LocalDateTime.now());
            return shoppingCart;
        }).collect(Collectors.toList());
        return shoppingCartMapper.insertList(shoppingCartList);
    }

    @Override
    public void paySuccess(String outTradeNo) {
        // 当前登录用户id
        Long userId = BaseContext.getCurrentId();

        // 根据订单号查询当前用户的订单
        Orders ordersDB = orderMapper.getByNumberAndUserId(outTradeNo, userId);

        // 根据订单id更新订单的状态、支付方式、支付状态、结账时间
        Orders orders = Orders.builder()
                .id(ordersDB.getId())
                .status(Orders.TO_BE_CONFIRMED)
                .payStatus(Orders.PAID)
                .checkoutTime(LocalDateTime.now())
                .build();

        orderMapper.update(orders);
    }

    @Override
    public void reminder(Long id) {
        OrderVO orders = orderMapper.findOrderById(id);
        if (orders == null) {
            throw new OrderBusinessException(MessageConstant.ORDER_NOT_FOUND);
        }

     /*   //基于WebSocket实现催单
        Map map = new HashMap();
        map.put("type", 2);//2代表用户催单
        map.put("orderId", id);
        map.put("content", "订单号：" + orders.getNumber());
        webSocketServer.sendToAllClient(JSON.toJSONString(map));*/


        log.info("用户催单{} ", orders.getId());
        JSONObject jsonData = new JSONObject();
        jsonData.put("type", 2);
        jsonData.put("orderId", orders.getId());
        jsonData.put("content", orders.getNumber());
        String s = JSON.toJSONString(jsonData);
        webSocketServer.sendToAllClient(s);
        log.info("用户催单{} 催单消息成功", orders.getId());

    }


}
